前端发展很快,现代浏览器原生 API 已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用场景大大减少。本项目总结了大部分 jQuery API 替代的方法,暂时只支持 IE10 以上浏览器。
Query Selector常用的 class、id、属性 选择器都可以使用 document.querySelector 或 document.querySelectorAll 替代。区别是
document.querySelector 返回第一个匹配的 Elementdocument.querySelectorAll 返回所有匹配的 Element 组成的 NodeList。它可以通过 [].slice.call() 把它转成 Array如果匹配不到任何 Element,jQuery 返回空数组 [],但 document.querySelector 返回 null,注意空指针异常。当找不到时,也可以使用 || 设置默认的值,如 document.querySelectorAll(selector) || []注意:document.querySelector 和 document.querySelectorAll 性能很差。如果想提高性能,尽量使用 document.getElementById、document.getElementsByClassName 或 document.getElementsByTagName。
1.0 选择器查询// jQuery$('selector');// Nativedocument.querySelectorAll('selector');1.1 class 查询// jQuery$('.class');// Nativedocument.querySelectorAll('.class');// ordocument.getElementsByClassName('class'); 1.2 id 查询// jQuery$('#id');// Nativedocument.querySelector('#id');// ordocument.getElementById('id');1.3 属性查询// jQuery$('a[target=_blank]');// Nativedocument.querySelectorAll('a[target=_blank]');1.4 后代查询// jQuery$el.find('li');// Nativeel.querySelectorAll('li');1.5 兄弟及上下元素兄弟元素// jQuery$el.siblings();// Native - latest, Edge13+[...el.parentNode.children].filter((child) => child !== el);// Native (alternative) - latest, Edge13+Array.from(el.parentNode.children).filter((child) => child !== el);// Native - IE10+Array.prototype.filter.call(el.parentNode.children, (child) => child !== el);上一个元素// jQuery$el.prev();// Nativeel.previousElementSibling;下一个元素// next$el.next();// Nativeel.nextElementSibling;1.6 ClosestClosest 获得匹配选择器的第一个祖先元素,从当前元素开始沿 DOM 树向上。
// jQuery$el.closest(queryString);// Native - Only latest, NO IEel.closest(selector);// Native - IE10+function closest(el, selector) { const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector; while (el) {if (matchesSelector.call(el, selector)) { return el;} else { el = el.parentElement;} } return null;}1.7 Parents Until获取当前每一个匹配元素集的祖先,不包括匹配元素的本身。
// jQuery$el.parentsUntil(selector, filter);// Nativefunction parentsUntil(el, selector, filter) { const result = []; const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector; // match start from parent el = el.parentElement; while (el && !matchesSelector.call(el, selector)) {if (!filter) { result.push(el);} else { if (matchesSelector.call(el, filter)) {result.push(el); }}el = el.parentElement; } return result;}1.8 FormInput/Textarea// jQuery$('#my-input').val();// Nativedocument.querySelector('#my-input').value;获取 e.currentTarget 在 .radio 中的数组索引// jQuery$('.radio').index(e.currentTarget);// NativeArray.prototype.indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);1.9 Iframe ContentsjQuery 对象的 iframe contents() 返回的是 iframe 内的 document
Iframe contents// jQuery$iframe.contents();// Nativeiframe.contentDocument;Iframe Query// jQuery$iframe.contents().find('.css');// Nativeiframe.contentDocument.querySelectorAll('.css');1.10 获取 body// jQuery$('body');// Nativedocument.body;1.11 获取或设置属性获取属性// jQuery$el.attr('foo');// Nativeel.getAttribute('foo');设置属性// jQuery, note that this works in memory without change the DOM$el.attr('foo', 'bar');// Nativeel.setAttribute('foo', 'bar');获取 data- 属性// jQuery$el.data('foo');// Native (use `getAttribute`)el.getAttribute('data-foo');// Native (use `dataset` if only need to support IE 11+)el.dataset['foo'];CSS & Style2.1 CSSGet style// jQuery$el.css("color");// Native// 注意:此处为了解决当 style 值为 auto 时,返回 auto 的问题const win = el.ownerDocument.defaultView;// null 的意思是不返回伪类元素win.getComputedStyle(el, null).color;Set style// jQuery$el.css({ color: "#ff0011" });// Nativeel.style.color = '#ff0011';Get/Set Styles注意,如果想一次设置多个 style,可以参考 oui-dom-utils 中 setStyles 方法
Add class// jQuery$el.addClass(className);// Nativeel.classList.add(className);Remove class// jQuery$el.removeClass(className);// Nativeel.classList.remove(className);has class// jQuery$el.hasClass(className);// Nativeel.classList.contains(className);Toggle class// jQuery$el.toggleClass(className);// Nativeel.classList.toggle(className); 2.2 Width & HeightWidth 与 Height 获取方法相同,下面以 Height 为例:
Window height// window height$(window).height();// 含 scrollbarwindow.document.documentElement.clientHeight;// 不含 scrollbar,与 jQuery 行为一致window.innerHeight;Document height// jQuery$(document).height();// Nativeconst body = document.body;const html = document.documentElement;const height = Math.max( body.offsetHeight, body.scrollHeight, html.clientHeight, html.offsetHeight, html.scrollHeight);Element height// jQuery$el.height();// Nativefunction getHeight(el) { const styles = this.getComputedStyle(el); const height = el.offsetHeight; const borderTopWidth = parseFloat(styles.borderTopWidth); const borderBottomWidth = parseFloat(styles.borderBottomWidth); const paddingTop = parseFloat(styles.paddingTop); const paddingBottom = parseFloat(styles.paddingBottom); return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;}// 精确到整数(border-box 时为 height - border 值,content-box 时为 height + padding 值)el.clientHeight;// 精确到小数(border-box 时为 height 值,content-box 时为 height + padding + border 值)el.getBoundingClientRect().height;2.3 Position & OffsetPosition获得匹配元素相对父元素的偏移
// jQuery$el.position();// Native{ left: el.offsetLeft, top: el.offsetTop }Offset获得匹配元素相对文档的偏移
// jQuery$el.offset();// Nativefunction getOffset (el) { const box = el.getBoundingClientRect(); return {top: box.top + window.pageYOffset - document.documentElement.clientTop,left: box.left + window.pageXOffset - document.documentElement.clientLeft }}2.4 ScrollTop获取元素滚动条垂直位置。
// jQuery$(window).scrollTop();// Native(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;DOM Manipulation3.1 Remove从 DOM 中移除元素。
// jQuery$el.remove();// Nativeel.parentNode.removeChild(el);3.2 TextGet text返回指定元素及其后代的文本内容。
// jQuery$el.text();// Nativeel.textContent;Set text设置元素的文本内容。
// jQuery$el.text(string);// Nativeel.textContent = string;3.3 HTMLGet HTML// jQuery$el.html();// Nativeel.innerHTML;Set HTML// jQuery$el.html(htmlString);// Nativeel.innerHTML = htmlString;3.4 AppendAppend 插入到子节点的末尾
// jQuery$el.append("hello");// Native (HTML string)el.insertAdjacentHTML('beforeend', 'Hello World');// Native (Element)el.appendChild(newEl);3.5 Prepend// jQuery$el.prepend("hello");// Native (HTML string)el.insertAdjacentHTML('afterbegin', 'Hello World');// Native (Element)el.insertBefore(newEl, el.firstChild);3.6 insertBefore在选中元素前插入新节点
// jQuery$newEl.insertBefore(queryString);// Native (HTML string)el.insertAdjacentHTML('beforebegin ', 'Hello World');// Native (Element)const el = document.querySelector(selector);if (el.parentNode) { el.parentNode.insertBefore(newEl, el);}3.7 insertAfter在选中元素后插入新节点
// jQuery$newEl.insertAfter(queryString);// Native (HTML string)el.insertAdjacentHTML('afterend', 'Hello World');// Native (Element)const el = document.querySelector(selector);if (el.parentNode) { el.parentNode.insertBefore(newEl, el.nextSibling);}3.8 is如果匹配给定的选择器,返回true
// jQuery$el.is(selector);// Nativeel.matches(selector);3.9 clone深拷贝被选元素。(生成被选元素的副本,包含子节点、文本和属性。)
//jQuery$el.clone();//Nativeel.cloneNode();注:深拷贝添加参数‘true’
3.10 empty移除所有子节点
//jQuery$el.empty();//Nativeel.innerHTML = '';3.11 wrap把每个被选元素放置在指定的HTML结构中。
//jQuery$(".inner").wrap('');//NativeArray.prototype.forEach.call(document.querySelector('.inner'), (el) => {const wrapper = document.createElement('div');wrapper.className = 'wrapper';el.parentNode.insertBefore(wrapper, el);el.parentNode.removeChild(el);wrapper.appendChild(el);});3.12 unwrap移除被选元素的父元素的DOM结构
// jQuery$('.inner').unwrap();// NativeArray.prototype.forEach.call(document.querySelectorAll('.inner'), (el) => { let elParentNode = el.parentNode if(elParentNode !== document.body) { elParentNode.parentNode.insertBefore(el, elParentNode) elParentNode.parentNode.removeChild(elParentNode) }});3.13 replaceWith用指定的元素替换被选的元素
//jQuery$('.inner').replaceWith('');//NativeArray.prototype.forEach.call(document.querySelectorAll('.inner'),(el) => { const outer = document.createElement("div"); outer.className = "outer"; el.parentNode.insertBefore(outer, el); el.parentNode.removeChild(el);});3.14 simple parse解析 HTML/SVG/XML 字符串
// jQuery$(` a b c d`);// Nativerange = document.createRange();parse = range.createContextualFragment.bind(range);parse(` a b c d`);AjaxFetch API 是用于替换 XMLHttpRequest 处理 ajax 的新标准,Chrome 和 Firefox 均支持,旧浏览器可以使用 polyfills 提供支持。
IE9+ 请使用 github/fetch,IE8+ 请使用 fetch-ie8,JSONP 请使用 fetch-jsonp。
4.1 从服务器读取数据并替换匹配元素的内容// jQuery$(selector).load(url, completeCallback)// Nativefetch(url).then(data => data.text()).then(data => { document.querySelector(selector).innerHTML = data}).then(completeCallback)Events完整地替代命名空间和事件代理,